# -*- coding:utf-8 -*-

import threading
import codecs
import sys, os

class SourceFile(threading.Thread):
	def __init__(self, filepath, filetype):
		threading.Thread.__init__(self)
		self.filepath = filepath
		self.filetype = filetype
		self.singlecomment = filetype[0]
		self.blockcomment_start = filetype[1]
		self.blockcomment_end = filetype[2]
		self.string_flag = filetype[3]
		self.commenttype = {0:'blank', 1:'code', 2:'single comment', 
							3:'code with comment', 4:'block comment begin', 
							5:'block comment end', 6:'block comment in one'}
		self.total = 0
		self.comment = 0
		self.blank = 0
		self.code = 0
		self.comment_percent = 0
		
	def chardet(self):
		for code in ('utf-8', 'gbk', 'gb2312'):
			try:
				f = codecs.open(self.filepath, 'r', code)
				f.close()
				return code
			except UnicodeDecodeError:
				pass
		f.close()
		return sys.getdefaultencoding()
	
	def check_comment_type(self, line):
	# 0: blank 1: code 2: single comment 3: code with comment 4: block comment start
	# 5: blockcomment end 6: block comment in one
		if len(line) == 0:	# blank line 0
			return 0
		elif line.startswith(self.singlecomment):	# single comment 2
			return 2
		elif line.startswith(self.blockcomment_start):	# block comment start detected
			if line.endswith(self.blockcomment_end) and \
			((line not in self.blockcomment_start) or (line not in self.blockcomment_end)) :	# block comment in one 6
				return 6
			else:	# block comment start 4
				return 4
		elif line.endswith(self.blockcomment_end):	# block comment end 5
			return 5
		elif self.singlecomment not in line:	# code 1 
			
			return 1
		else:	# code with comment 3 or code 1
			line = self.clean_line(line)
			if self.singlecomment in line:
				return 3
			else:
				return 1
	
	def clean_line(self, line):
		string_start = 0
		string_end = 0
		string_stat = False
		fond_one = False
		string_char = ''
		for i in range(len(line)):
			if line[i] in self.string_flag and string_stat == False:
				string_start = i
				string_stat = True
				string_char = line[i]
			elif line[i] == string_char and string_stat == True:
				string_end = i
				string_stat = False
				fond_one = True
				break
		if fond_one:
			line = line[:string_start] + line[string_end + 1:]
			fond_one = False
			line = self.clean_line(line)
		return line
	
	def counting(self):
		code = self.chardet()
		f = codecs.open(self.filepath, 'r', code)
		in_block = False
		for line in f:
			t = self.check_comment_type(line.strip())
			self.total += 1
			if t in (4, 5) and not in_block:
				in_block = True
				self.comment += 1
			elif t in (4, 5) and in_block:
				in_block = False
				self.comment += 1
			if in_block and t not in (4, 5):
				self.comment += 1
			else:
				if t == 0:
					self.blank += 1
				elif t == 1:
					self.code += 1
				elif t == 2 or t == 6:
					self.comment += 1
				elif t == 3:
					self.comment += 1
					self.code += 1
		f.close()
		if self.code != 0:
			self.comment_percent = self.comment/(self.comment + self.code)
		else:
			self.comment_percent = 0
		
	def show(self):
		print(os.path.basename(self.filepath) + ': ', self.blank, self.code, self.comment, \
				self.total, '%.2f' % (self.comment_percent*100) + '%') 
			
	def run(self):
		try:
			self.counting()
			self.show()
		except Exception as err:
			print(err)
			sys.exit(1)
		
